home *** CD-ROM | disk | FTP | other *** search
- /*
- File: GXEditFileIO.c
-
- Contains:
-
- Written by: Barton R. House
-
- Copyright: © 1993 by Apple Computer, Inc., All rights reserved.
-
- */
-
- #include "GXEdit.h"
- #include "GXEditDoc.h"
- #include "GXEditDebug.h"
- #include "GXEditError.h"
- #include "GXEditUtils.h"
- #include "GXEditSelection.h"
- #include "GXEditValidation.h"
- #include "GXEditStyle.h"
-
- /* GX includes */
-
- #include "graphics toolbox.h"
- #include "graphics routines.h"
- #include "math routines.h"
-
- #define kBufferSize 2056
-
- static void WriteParagraph(short fRefNum, ParaPtr pp);
- static void WriteLine(short fRefNum, LinePtr lp);
- static void WriteNewRun(short fRefNum, NewRunPtr rp);
- static void WriteStyle(DocPtr dp, short fRefNum, StylePtr sp);
- static void WriteData(short fRefNum, Ptr p, long size);
- static void WriteLong(short fRefNum, long l);
- static void WriteShort(short fRefNum, short s);
- static void WriteBoolean(short fRefNum, Boolean b);
-
-
- static void ReadParagraph(DocPtr dp, short fRefNum, ParaPtr pp);
- static void ReadLine(short fRefNum, LinePtr lp);
- static void ReadNewRun(DocPtr dp, short fRefNum, NewRunPtr rp);
- static void ReadStyle(DocPtr dp, short fRefNum, StylePtr sp);
- static void ReadLayout(DocPtr dp, short fRefNum, gxShape * layoutPtr);
- static void ReadData(short fRefNum, Ptr p, long size);
- static void ReadLong(short fRefNum, long * l);
- static void ReadShort(short fRefNum, short * s);
- static void ReadBoolean(short fRefNum, Boolean * b);
-
- boolean gGXEditForceReflowOnOpenDoc = false;
-
- /* FILE FORMAT - Version 1
-
- magic long
- version long
-
- doc
-
- length long
- numStyles short
- numText long
- numParagraphs short
- top long
- vertical Boolean (added in version 1)
-
- selection
-
- startDocOffset long
- endDocOffset long
- endOfLine Boolean
-
- styles[numStyles]
-
- styleSize long
-
- flatten data char[styleSize]
-
- paragraphs[numPara]
-
- start short
- width short
- height short
- docOffset long
- numText short
- numLines short
- numRuns short
- options gxLayoutOptions (this should be a private data structure)
-
- lines[numLines]
-
- start short
- paraOffset short
- numText short
-
- runs[numRuns]
-
- styleIndex short
- paraOffset short
- numText short
- textSize short
-
- text char[numText * textSize]
-
- */
-
- typedef struct {
- gxSpoolBlock sb; /* this must be first */
- short fRefNum;
- long start;
- long numBytes;
- DocPtr dp;
- } MySpoolBlock;
-
- static long MySpoolProcedure(gxSpoolCommand command, gxSpoolBlock * sb);
-
- void DocSave(DocPtr dp, short fRefNum)
- {
- ParaPtr pp;
- StylePtr sp;
- short paragraphIndex;
- short styleIndex;
-
- /* write out magic */
-
- WriteLong(fRefNum, kGXEditMagic);
-
- /* write out file format version */
-
- WriteLong(fRefNum, kGXEditFileVersion);
-
- /* write out the document information */
-
- WriteLong(fRefNum, dp->length);
- WriteShort(fRefNum, dp->numStyles);
- WriteLong(fRefNum, dp->numText);
- WriteShort(fRefNum, dp->numParagraphs);
- WriteLong(fRefNum, dp->top);
- WriteBoolean(fRefNum, dp->verticalText);
-
- /* write out selection information */
-
- WriteLong(fRefNum, dp->selection.startDocOffset);
- WriteLong(fRefNum, dp->selection.endDocOffset);
- WriteBoolean(fRefNum, dp->selection.endOfLine);
-
- /* write out gxStyle information */
-
- HLock((Handle) dp->styles);
-
- for(sp = *dp->styles, styleIndex = 0; styleIndex < dp->numStyles; styleIndex++, sp++)
- WriteStyle(dp, fRefNum, sp);
-
- HUnlock((Handle) dp->styles);
-
- /* write out the paragraphs */
-
- HLock((Handle) dp->paragraphs);
-
- for(paragraphIndex=0, pp = *dp->paragraphs; paragraphIndex < dp->numParagraphs; paragraphIndex++,pp++)
- WriteParagraph(fRefNum, pp);
-
- HUnlock((Handle) dp->paragraphs);
-
- }
-
- static void WriteParagraph(short fRefNum, ParaPtr pp)
- {
- LinePtr lp;
- short lineIndex;
- NewRunPtr rp;
- short runIndex;
-
- WriteShort(fRefNum, pp->start);
- WriteShort(fRefNum, pp->width);
- WriteShort(fRefNum, pp->height);
- WriteLong(fRefNum, pp->docOffset);
- WriteShort(fRefNum, pp->numText);
- WriteShort(fRefNum, pp->numLines);
- WriteShort(fRefNum, pp->numRuns);
-
- /* this should really use a private structure */
-
- WriteData(fRefNum, (Ptr) &pp->layoutOptions, sizeof(pp->layoutOptions));
-
- /* write out lines */
-
- HLock((Handle) pp->lines);
-
- for(lineIndex=0, lp = *pp->lines; lineIndex < pp->numLines; lineIndex++, lp++)
- WriteLine(fRefNum, lp);
-
- HUnlock((Handle) pp->lines);
-
- /* write out runs */
-
- HLock((Handle) pp->runs);
-
- for(runIndex = 0, rp = *pp->runs; runIndex < pp->numRuns; runIndex++, rp++)
- WriteNewRun(fRefNum, rp);
-
- HUnlock((Handle) pp->runs);
-
- }
-
- static void WriteLine(short fRefNum, LinePtr lp)
- {
- WriteShort(fRefNum, lp->start);
- WriteShort(fRefNum, lp->paraOffset);
- WriteShort(fRefNum, lp->numText);
-
- }
-
- static void WriteNewRun(short fRefNum, NewRunPtr rp)
- {
- WriteShort(fRefNum, rp->styleIndex);
- WriteShort(fRefNum, rp->paraOffset);
- WriteShort(fRefNum, rp->numText);
- WriteShort(fRefNum, 0); /* WriteShort(fRefNum, rp->textSize); */
-
- /* save out text */
-
- HLock((Handle) rp->text);
-
- WriteData(fRefNum, *rp->text, rp->numText);
-
- HUnlock((Handle) rp->text);
-
- }
-
- static void WriteStyle(DocPtr dp, short fRefNum, StylePtr sp)
- {
- MySpoolBlock msb;
- gxShape emptyShape;
- long startOfStyle;
- long endOfStyle;
- long styleSize;
- OSErr err;
-
- /* save the file position of start of gxStyle */
-
- GetFPos(fRefNum, &startOfStyle);
-
- /* save out the size of the flatten gxStyle */
-
- styleSize = 0; /* we don't know how big the flatten gxStyle is yet */
-
- WriteLong(fRefNum, styleSize);
-
- /* save out the flatten gxStyle information */
-
- msb.sb.buffer = NewPtr(kBufferSize);
- msb.sb.bufferSize = kBufferSize;
- msb.sb.spoolProcedure = MySpoolProcedure;
-
- GetFPos(fRefNum, &msb.start);
-
- msb.fRefNum = fRefNum;
- msb.numBytes = 0;
- msb.dp = dp;
-
- /* create an empty gxShape and set the gxStyle to the gxStyle we want to save */
-
- emptyShape = GXNewShape(gxEmptyType);
- GXSetShapeStyle(emptyShape, sp->textStyle);
-
- /* look into setting the flags so that a list of fonts that are used is generated */
-
- GXFlattenShape(emptyShape, (gxFlattenFlag) 0, (gxSpoolBlock *) &msb);
-
- /* dispose of the temporary gxShape */
-
- GXDisposeShape(emptyShape);
-
- /* now record the file position for the end of the gxStyle */
-
- GetFPos(fRefNum, &endOfStyle);
-
- /* double check the file position with the number of bytes written */
-
- if(msb.numBytes + msb.start != endOfStyle)
- gxEditPostError(dp, gx_edit_internal_fatal_error);
-
- /* finish up recording the size of the flatten gxStyle */
-
- styleSize = endOfStyle - msb.start;
-
- if((err = SetFPos(fRefNum, fsFromStart, startOfStyle)) != noErr)
- gxEditPostError(dp, gx_edit_internal_fatal_error);
-
- WriteLong(fRefNum, styleSize);
-
- if((err = SetFPos(fRefNum, fsFromStart, endOfStyle)) != noErr)
- gxEditPostError(dp, gx_edit_internal_fatal_error);
-
- /* free up the buffer */
-
- DisposePtr(msb.sb.buffer);
-
- }
-
-
- static void WriteData(short fRefNum, Ptr p, long size)
- {
- long count;
- OSErr err;
-
- count = size;
-
- if((err = FSWrite(fRefNum, &count, p)) != noErr)
- gxEditPostError(nil, gx_edit_internal_fatal_error);
-
- if(count != size)
- gxEditPostError(nil, gx_edit_internal_fatal_error);
-
- }
-
- static void WriteLong(short fRefNum, long l)
- {
- WriteData(fRefNum, (Ptr) &l, sizeof(long));
- }
-
- static void WriteShort(short fRefNum, short s)
- {
- WriteData(fRefNum, (Ptr) &s, sizeof(short));
- }
-
- static void WriteBoolean(short fRefNum, Boolean b)
- {
- WriteData(fRefNum, (Ptr) &b, sizeof(Boolean));
- }
-
- void DocOpen(DocHan * docHanPtr, Rect * viewRect, gxViewPort docViewPort, short fRefNum, short leftMargin, short rightMargin)
- {
- DocHan doc;
- DocPtr dp;
- ParaPtr pp;
- StylePtr sp;
- short paraIndex;
- short styleIndex;
- gxViewPort newViewPort;
- gxShape clip;
- gxRectangle rect;
- long magic;
- long version;
-
- doc = (DocHan) NewHandle(sizeof(DocRec));
-
- HLock((Handle) doc);
-
- dp = *doc;
-
- /* read in magic */
-
- ReadLong(fRefNum, &magic);
-
- if(magic != kGXEditMagic)
- gxEditPostError(nil, gx_edit_internal_fatal_error);
-
- /* read the file format version */
-
- ReadLong(fRefNum, &version);
-
- if(version != kGXEditFileVersion && version != kGXEditFileVersion0)
- gxEditPostError(nil, gx_edit_internal_fatal_error);
-
- /* read the the document information */
-
- ReadLong(fRefNum, &dp->length);
- ReadShort(fRefNum, &dp->numStyles);
- ReadLong(fRefNum, &dp->numText);
- ReadShort(fRefNum, &dp->numParagraphs);
- ReadLong(fRefNum, &dp->top);
- if(version != kGXEditFileVersion0)
- ReadBoolean(fRefNum, &dp->verticalText);
- else
- dp->verticalText = false;
-
- /* read the selection information */
-
- ReadLong(fRefNum, &dp->selection.startDocOffset);
- ReadLong(fRefNum, &dp->selection.endDocOffset);
- ReadBoolean(fRefNum, &dp->selection.endOfLine);
-
- /* set generic doc information */
-
- dp->magic = magic;
- dp->active = false;
-
- /* set the error control values */
-
- dp->errorProc = nil;
- dp->error = 0;
- dp->stickyError = 0;
-
- /* set the correct view port and view rect */
-
- dp->lineWidth = viewRect->right - viewRect->left - leftMargin - rightMargin;
- dp->leftMargin = leftMargin;
- dp->rightMargin = rightMargin;
-
- if(dp->verticalText)
- dp->viewHeight = viewRect->right - viewRect->left;
- else
- dp->viewHeight = viewRect->bottom - viewRect->top;
-
- dp->viewRect = *viewRect;
-
- newViewPort = GXCopyToViewPort(nil, docViewPort);
- GXSetViewPortParent(newViewPort, docViewPort);
- rect.top = ff(viewRect->top);
- rect.left = ff(viewRect->left);
- rect.right = ff(viewRect->right);
- rect.bottom = ff(viewRect->bottom);
- clip = GXNewRectangle(&rect);
-
- /* This ignores is needed because we do not keep track of the current
- clip of the view port. Thus, we will often set the clip to the same rect
- which generates a notice*/
-
- #ifdef debugging
- GXIgnoreGraphicsNotice(clip_already_set);
- #endif
-
- GXSetViewPortClip(newViewPort, clip);
-
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
-
- GXDisposeShape(clip);
-
- dp->docViewPort = newViewPort;
-
- /* allocate offscreen gxBitmap and viewport */
-
- dp->offscreenBytes = nil;
- dp->offscreenPort = nil;
- dp->offscreenDevice = nil;
- dp->offscreenGroup = nil;
- dp->offscreenBitmap = nil;
-
- gxEditBuildOffscreen(dp);
-
- /* read in the styles */
-
- dp->styles = (StyleHan) NewHandle(sizeof(StyleRec) * dp->numStyles);
-
- HLock((Handle) dp->styles);
-
- for(styleIndex=0, sp = *dp->styles; styleIndex<dp->numStyles; styleIndex++, sp++)
- ReadStyle(dp, fRefNum, sp);
-
- HUnlock((Handle) dp->styles);
-
- /* read in the paragraphs */
-
- dp->paragraphs = (ParaHan) NewHandle(sizeof(ParaRec) * dp->numParagraphs);
-
- HLock((Handle) dp->paragraphs);
-
- for(paraIndex=0, pp = *dp->paragraphs; paraIndex<dp->numParagraphs; paraIndex++, pp++)
- ReadParagraph(dp, fRefNum, pp);
-
- HUnlock((Handle) dp->paragraphs);
-
- /* initialize empty scrap */
-
- dp->scrap.numText = 0;
- dp->scrap.numRuns = 0;
- dp->scrap.runs = (NewRunHan) NewHandle(0);
-
- /* invalidate the entire document for drawing purposes */
-
- dp->drawn = false;
-
- /* set the paragraph widths and reflow if the paragraph width has changed */
-
- pp = *dp->paragraphs;
-
- for(paraIndex = 0; paraIndex < dp->numParagraphs; paraIndex++, pp++)
- if(pp->width != dp->lineWidth || gGXEditForceReflowOnOpenDoc) {
-
- pp->width = dp->lineWidth;
- pp->layoutOptions.width = ff(pp->width);
-
- if(pp->numLines) {
-
- pp->reflow = true;
- (*pp->lines)[0].reflow = true;
-
- }
-
- }
-
- /* setup the current selection */
-
- dp->numCurrentFonts = 0;
- dp->currentFonts = (gxFont **) NewHandle(0);
-
- dp->numCurrentStyles = 0;
- dp->currentStyles = (short **) NewHandle(0);
-
- dp->currentSize = 0;
- dp->emptyStyle = 0;
-
- SetSelection(dp, dp->selection.startDocOffset, dp->selection.endDocOffset, true, dp->selection.endOfLine, true);
-
- DocSetMaxTop(dp);
-
- ValidateDoc(dp);
-
- if (gGXEditForceReflowOnOpenDoc)
- while (DocReflow(dp))
- ;
-
- HUnlock((Handle) doc);
-
- *docHanPtr = doc;
- }
-
- static void ReadParagraph(DocPtr dp, short fRefNum, ParaPtr pp)
- {
- LinePtr lp;
- short lineIndex;
- NewRunPtr rp;
- short runIndex;
-
- ReadShort(fRefNum, &pp->start);
- ReadShort(fRefNum, &pp->width);
- ReadShort(fRefNum, &pp->height);
- ReadLong(fRefNum, &pp->docOffset);
- ReadShort(fRefNum, &pp->numText);
- ReadShort(fRefNum, &pp->numLines);
- ReadShort(fRefNum, &pp->numRuns);
-
- pp->drawn = false;
- pp->reflow = false;
- pp->dirty = false; /* the line heights and starts are still good */
-
- /* this should really use a private structure */
-
- ReadData(fRefNum, (Ptr) &pp->layoutOptions, sizeof(pp->layoutOptions));
-
- /* adjust the layout options */
-
- pp->layoutOptions.baselineRec = nil; /* FUTURE ENHANCEMENT -- THIS SHOULD BE RESTORED */
-
- /* read in the lines */
-
- pp->lines = (LineHan) NewHandle(pp->numLines * sizeof(LineRec));
-
- HLock((Handle) pp->lines);
-
- for(lineIndex = 0, lp = *pp->lines; lineIndex < pp->numLines; lineIndex++, lp++)
- ReadLine(fRefNum, lp);
-
- HUnlock((Handle) pp->lines);
-
- /* read in runs */
-
- pp->runs = (NewRunHan) NewHandle(pp->numRuns * sizeof(NewRunRec));
-
- HLock((Handle) pp->runs);
-
- for(runIndex = 0, rp = *pp->runs; runIndex < pp->numRuns; runIndex++, rp++)
- ReadNewRun(dp, fRefNum, rp);
-
- HUnlock((Handle) pp->runs);
-
- }
-
-
- static void ReadLine(short fRefNum, LinePtr lp)
- {
- #pragma unused(dp)
-
- ReadShort(fRefNum, &lp->start);
- ReadShort(fRefNum, &lp->paraOffset);
- ReadShort(fRefNum, &lp->numText);
-
- lp->layout = nil;
- lp->layoutPos.x = 0; lp->layoutPos.y = 0;
- lp->dirty = true;
- lp->reflow = false;
- lp->drawn = false;
- lp->selected = false;
-
- lp->ascent = 0;
- lp->descent = 0;
-
- }
-
- static void ReadNewRun(DocPtr dp, short fRefNum, NewRunPtr rp)
- {
- short dummy;
-
- ReadShort(fRefNum, &rp->styleIndex);
-
- IncrementDocStyleRefCount(dp, rp->styleIndex);
-
- ReadShort(fRefNum, &rp->paraOffset);
- ReadShort(fRefNum, &rp->numText);
- ReadShort(fRefNum, &dummy); /* ReadShort(fRefNum, &rp->textSize); */
-
- /* read in text */
-
- rp->text = (void **) NewHandle(rp->numText);
-
- HLock((Handle) rp->text);
-
- ReadData(fRefNum, *rp->text, rp->numText);
-
- HUnlock((Handle) rp->text);
-
- }
-
- static void ReadStyle(DocPtr dp, short fRefNum, StylePtr sp)
- {
- MySpoolBlock msb;
- gxShape emptyShape;
- long styleSize;
-
- ReadLong(fRefNum, &styleSize);
-
- /* readin the GX gxStyle information */
-
- msb.sb.buffer = NewPtr(kBufferSize);
- msb.sb.bufferSize = kBufferSize;
- msb.sb.spoolProcedure = MySpoolProcedure;
-
- GetFPos(fRefNum, &msb.start);
-
- msb.numBytes = styleSize;
-
- msb.fRefNum = fRefNum;
- msb.dp = dp;
-
- emptyShape = GXUnflattenShape((gxSpoolBlock *) &msb, 1, &dp->docViewPort );
-
- sp->textStyle = GXGetShapeStyle(emptyShape); /* this does not increment the owner count */
- sp->textStyle = GXCopyToStyle(nil, sp->textStyle);
-
- GXDisposeShape(emptyShape);
-
- /* check that the correct number of bytes was read */
-
- if(msb.numBytes != 0)
- gxEditPostError(dp, gx_edit_internal_fatal_error);
-
- DisposePtr(msb.sb.buffer);
-
- /* initialize the redundant data */
-
- sp->textFont = GXGetStyleFont(sp->textStyle);
- sp->textSize = FixedToInt(GXGetStyleTextSize(sp->textStyle));
- sp->platform = GXGetStyleEncoding(sp->textStyle, &sp->script, &sp->language);
-
- /* initial zero value for refCount */
-
- sp->refCount = 0;
- }
-
- static void ReadData(short fRefNum, Ptr p, long size)
- {
- long count;
- OSErr err;
-
- count = size;
-
- if((err = FSRead(fRefNum, &count, p)) != noErr)
- gxEditPostError(nil, gx_edit_internal_fatal_error);
-
- if(count != size)
- gxEditPostError(nil, gx_edit_internal_fatal_error);
-
- }
-
- static void ReadLong(short fRefNum, long * l)
- {
- ReadData(fRefNum, (Ptr) l, sizeof(long));
- }
-
- static void ReadShort(short fRefNum, short * s)
- {
- ReadData(fRefNum, (Ptr) s, sizeof(short));
- }
-
- static void ReadBoolean(short fRefNum, Boolean * b)
- {
- ReadData(fRefNum, (Ptr) b, sizeof(Boolean));
- }
-
- static long MySpoolProcedure(gxSpoolCommand command, gxSpoolBlock * sb)
- {
- long count;
- MySpoolBlock * msb;
- OSErr err;
-
- msb = (MySpoolBlock *) sb;
-
- switch(command) {
-
- case gxOpenReadSpool:
- case gxOpenWriteSpool:
-
- SetFPos(msb->fRefNum, fsFromStart, msb->start);
- break;
-
- case gxReadSpool:
-
- count = sb->count;
-
- if(count > msb->numBytes) {
-
- count = msb->numBytes;
- sb->bufferSize = msb->numBytes;
-
- }
-
- if((err = FSRead(msb->fRefNum, &count, sb->buffer)) != noErr)
- gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
-
- if((sb->count > msb->numBytes && count != msb->numBytes) ||
- (sb->count <= msb->numBytes && count != sb->count))
- gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
-
- msb->numBytes -= count;
-
- break;
-
- case gxWriteSpool:
-
- count = sb->count;
-
- if((err = FSWrite(msb->fRefNum, &count, sb->buffer)) != noErr)
- gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
-
- if(sb->count != count)
- gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
-
- msb->numBytes += count;
-
- break;
-
- case gxCloseSpool:
- break;
- }
-
- return(noErr);
-
- }
-